import { Callout, Sandpack } from '@/components'

# infiniteQueryOptions

<Callout type='warning'>

**@suspensive/react-query에서 Deprecated**

이 인터페이스는 이제 TanStack Query v4.41.0+에서 공식적으로 지원됩니다. TanStack Query에서 백포팅했으므로, @suspensive/react-query의 백포팅된 버전을 deprecated 처리합니다. 공식 TanStack Query 인터페이스로 마이그레이션하세요:

```diff
- import { infiniteQueryOptions } from '@suspensive/react-query'
+ import { infiniteQueryOptions } from '@tanstack/react-query'
```

자세한 내용은 [TanStack Query PR #9334](https://github.com/TanStack/query/pull/9334)을 참고하세요.

</Callout>

`infiniteQueryOptions`는 Infinite Query에서 queryOptions를 활용할 수 있도록 도와줍니다. 이는 [`queryOptions`](https://suspensive.org/ko/docs/react-query/queryOptions)가 사용되는 이유와 유사한 장점을 제공합니다.

```jsx /infiniteQueryOptions/
import { infiniteQueryOptions, useSuspenseInfiniteQuery, SuspenseInfiniteQuery } from '@suspensive/react-query'
import { useInfiniteQuery, useQueryClient } from '@tanstack/react-query'

const postsInfiniteQueryOptions = (page) =>
  infiniteQueryOptions({
    queryKey: ['posts', page] as const,
    queryFn: ({
      queryKey: [, page], // queryKey를 활용할 수 있습니다.
    }) => fetch(`https://example.com/posts?page=${page}`).then(res => res.json()),
    getNextPageParam: (lastPage) => lastPage.nextPage ?? false,
  })

// 커스텀 쿼리 훅을 만들 필요가 없습니다.
// useInfiniteQuery, useSuspenseInfiniteQuery, SuspenseInfiniteQuery에서 직접 infiniteQueryOptions를 활용할 수 있습니다.
const postsQuery = useInfiniteQuery(postsInfiniteQueryOptions(1))
const { data: posts, fetchNextPage, hasNextPage } = useSuspenseInfiniteQuery({
  ...postsInfiniteQueryOptions(1),
  refetchInterval: 2000, // 사용처에서 확장성을 명확히 표현됩니다.
})
const Example = () => (
  <SuspenseInfiniteQuery {...postsInfiniteQueryOptions(1)}>
    {({ data, fetchNextPage, hasNextPage }) => (
      <div>
        {data.pages.map((page, index) => (
          <div key={index}>
            {page.posts.map(post => (
              <div key={post.id}>{post.title}</div>
            ))}
          </div>
        ))}
        <button onClick={() => fetchNextPage()} disabled={!hasNextPage}>
          Load More
        </button>
      </div>
    )}
  </SuspenseInfiniteQuery>
)

// queryClient의 메소드에서 queryKey와 queryFn을 쉽게 활용할 수 있습니다.
const queryClient = useQueryClient()
queryClient.refetchQueries(postsInfiniteQueryOptions(1))
queryClient.prefetchQuery(postsInfiniteQueryOptions(1))
queryClient.invalidateQueries(postsInfiniteQueryOptions(1))
queryClient.fetchQuery(postsInfiniteQueryOptions(1))
queryClient.resetQueries(postsInfiniteQueryOptions(1))
queryClient.cancelQueries(postsInfiniteQueryOptions(1))
```

<Sandpack>

```tsx Example.tsx active
import { Suspense } from '@suspensive/react'
import {
  infiniteQueryOptions,
  SuspenseInfiniteQuery,
} from '@suspensive/react-query'
import { useQueryClient } from '@tanstack/react-query'
import { getPosts } from './api'

const postsInfiniteQueryOptions = (page) =>
  infiniteQueryOptions({
    queryKey: ['posts', page],
    queryFn: ({ queryKey: [, page] }) => getPosts(page),
    getNextPageParam: (lastPage) => lastPage.nextPage ?? false,
  })

export const Example = () => {
  const queryClient = useQueryClient()

  return (
    <div>
      <button
        onClick={() => queryClient.resetQueries(postsInfiniteQueryOptions(1))}
      >
        Reset Query
      </button>
      <Suspense fallback={<div>Loading...</div>}>
        <SuspenseInfiniteQuery {...postsInfiniteQueryOptions(1)}>
          {({ data, fetchNextPage, hasNextPage }) => (
            <div>
              {data.pages.map((page, index) => (
                <div key={index}>
                  {page.posts.map((post) => (
                    <div key={post.id}>
                      <h1>{post.title}</h1>
                      <p>{post.body}</p>
                    </div>
                  ))}
                </div>
              ))}
              <button onClick={() => fetchNextPage()} disabled={!hasNextPage}>
                Load More
              </button>
            </div>
          )}
        </SuspenseInfiniteQuery>
      </Suspense>
    </div>
  )
}
```

```tsx api.ts
type Post = {
  userId: number
  id: number
  title: string
  body: string
}

type PostsResponse = {
  posts: Post[]
  nextPage: number
}

export const getPosts = async (page: number): Promise<PostsResponse> => {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=2`
  )

  if (!response.ok) {
    throw new Error('An error occurred')
  }

  const data = await response.json()
  const nextPage = page + 1

  return { posts: data, nextPage }
}
```

</Sandpack>

### 버전 기록

| Version  | Changes                                                                                                                 |
| -------- | ----------------------------------------------------------------------------------------------------------------------- |
| `v3.0.0` | `networkMode`는 제거되었습니다. 자세한 내용은 [v3로 마이그레이션하기 문서](./migration/migrate-to-v3.mdx)를 참고하세요. |
